#include<bits/stdc++.h>
#define int long long
#define rep(i,a,b) for(int i(a);i<=(b);++i)
#define req(i,a,b) for(int i(a);i>=(b);--i)
#define sort stable_sort
using namespace std;
char buf[1<<23],*p1=buf,*p2=buf,ubuf[1<<23],*u=ubuf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
template<typename TP> inline TP read(TP &num)
{
	TP x=0;
	int f=0;
	char ch=getchar();
	while(ch<48||ch>57) f|=ch=='-',ch=getchar();
	while(48<=ch&&ch<=57) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return num=f?-x:x;
}
template<typename ...Args> inline void read(Args &...args)
{
	(read(args),...);
}
template<typename TP> inline void write(TP x)
{
	(x<0)?(putchar('-'),x=-x):0;
	(x>9)?(write(x/10),0):0;
	putchar((x%10)^48);
}
template<typename TP> inline void writeln(TP x)
{
	write<TP>(x);
	puts("");
}
signed main()
{
	freopen("mcmf.in","r",stdin);
	freopen("mcmf.out","w",stdout);
	int n; read(n);
	vector<int> k(n+1);
	vector<vector<int>> a(n+1,vector<int>());
	auto Print=[&](bitset<100003> x)
	{
		int appear=0;
		req(i,100002,0)
		{
			if(x[i]) appear=1;
			if(appear) putchar(x[i]+48);
		}
		putchar(10);
	};
	if(n==2)
	{
		rep(i,1,n)
		{
			read(k[i]);
			a[i].resize(k[i]+1);
			rep(j,1,k[i]) read(a[i][j]),--a[i][j];
			sort(a[i].begin()+1,a[i].end());
		}
		auto Min=[&](bitset<100003> x,bitset<100003> y)
		{
			rep(i,0,100002) if(x[i]>y[i]) return y; else if(x[i]<y[i]) return x;
			return x;
		};
		bitset<100003> res1=0,res2=0,rres1=0,rres2=0;
		rres1.set(),rres2.set();
		// option 1: choose 1 first
		rep(i,1,k[1]) res1[a[1][i]]=1;
		int mx=*max_element(a[2].begin(),a[2].end()),ok=0;
		if(!res1[mx])
		{
			ok=1;
			int pre=114514;
			req(i,k[2],1)
			{
				if(res1[a[2][i]]&&rres1._Find_next(a[2][i])>pre)
				{
					ok=0;
					break;
				}
				pre=res1[a[2][i]]?a[2][i]:rres1._Find_next(a[2][i]);
				if(res1[a[2][i]]) break;
			}
			if(ok) req(i,k[2],1) if(!a[2][i])
			{
				res1[a[2][i]]=1;
				rres1[a[2][i]]=0;
			} else
			{
				int P=rres1._Find_next(a[2][i]);
				res1[P]=1;
				rres1[P]=0;
				break;
			}
		}
		if(!ok)
		{
			int pos=mx+1;
			while(res1[pos]) ++pos;
			res1[pos]=1;
		}
		// option 2: choose 2 first
		rep(i,1,k[2]) res2[a[2][i]]=1;
		mx=*max_element(a[1].begin(),a[1].end()),ok=0;
		if(!res2[mx])
		{
			ok=1;
			int pre=114514;
			req(i,k[1],1)
			{
				if(res2[a[1][i]]&&rres2._Find_next(a[1][i])>pre)
				{
					ok=0;
					break;
				}
				pre=res2[a[1][i]]?a[1][i]:rres2._Find_next(a[1][i]);
				if(res2[a[1][i]]) break;
			}
			if(ok) req(i,k[1],1) if(!a[1][i])
			{
				res2[a[1][i]]=1;
				rres2[a[1][i]]=0;
			} else
			{
				int P=rres2._Find_next(a[1][i]);
				res2[P]=1;
				rres2[P]=0;
				break;
			}
		}
		if(!ok)
		{
			int pos=mx+1;
			while(res2[pos]) ++pos;
			res2[pos]=1;
		}
		Print(Min(res1,res2));
	}
	else
	{
		rep(i,1,n)
		{
			read(k[i]);
			a[i].resize(k[i]+1);
			rep(j,1,k[i]) read(a[i][j]),--a[i][j];
			sort(a[i].begin()+1,a[i].end());
		}
		sort(a.begin()+1,a.end(),[](vector<int> x,vector<int> y){return *max_element(x.begin(),x.end())<*max_element(y.begin(),y.end());});
		bitset<100003> ans=0,revans=0;
		revans.set();
		rep(i,1,n)
		{
			int mx=*max_element(a[i].begin(),a[i].end()),ok=0;
			if(!ans[mx])
			{
				ok=1;
				int pre=114514;
				req(j,(int)a[i].size()-1,1)
				{
					if(ans[a[i][j]]&&revans._Find_next(a[i][j])>pre)
					{
						ok=0;
						break;
					}
					pre=ans[a[i][j]]?a[i][j]:revans._Find_next(a[i][j]);
					if(ans[a[i][j]]) break;
				}
				if(ok) req(j,(int)a[i].size()-1,1) if(!a[i][j])
				{
					ans[a[i][j]]=1;
					revans[a[i][j]]=0;
				} else
				{
					int P=revans._Find_next(a[i][j]);
					ans[P]=1;
					revans[P]=0;
					break;
				}
			}
			if(!ok)
			{
				int pos=revans._Find_next(mx);
				revans[pos]=0,ans[pos]=1;
			}
		}
		Print(ans);
	}
	return 0;
}
